Chapter 13 THE ACCESS TYPE VARIABLE THE ACCESS TYPE IS DIFFERENT _________________________________________________________________ The access type variable is different from every =============== other type we have encountered because it is not ACCESS1.ADA actually a variable which can store a piece of =============== data, but contains the address of another piece of data which can be manipulated. As always the best teacher is an example, so examine the file named ACCESS1.ADA for an example program with a few access type variables in it. DECLARING AN ACCESS TYPE VARIABLE _________________________________________________________________ In line 10 we declare a new type, an access type. As with all types, the reserved word type is given, followed by the type name, then the reserved words is and the type definition. The type definition begins with the reserved word access, which denotes an access type variable, then by the type which we wish to access. The type which we wish to access can be any type which has been declared prior to this point in the program, either a predeclared type or a type we have declared. Because there are no predeclared access types available in Ada, we must declare all access types we wish to use. The new type is used to declare three access variables in line 11. No actual variables are declared, only access to three places in memory which actually do not exist yet. The access type variables do not store an integer value, as might be expected, but instead store the address of an integer value located somewhere within the address space of the computer memory. Figure 13-1 illustrates graphically the condition of the system at this point. A box with a dot in the center depicts an access variable and an empty box will be used to depict a scalar variable. WE NEED SOME DATA TO POINT AT _________________________________________________________________ As we begin the executable part of the program, we have no data to access, so we create some data storage in line 14 using the new reserved word. This tells the system to go somewhere and create a variable of type INTEGER, with no name, and cause the access variable named Index to point at this new variable. The effective address of the new variable is assigned to the access variable Index, but the new variable still has no assigned value. Page 13-1 Chapter 13 - The Access Type Variable Line 15 tells the system to assign the value of 13 to the new variable by using a very strange looking method of doing so. For the first two example programs in this chapter, we will simply say that the value of all of the variable is set to the indicated value, namely 13. The end result is that the access variable named Index is pointing someplace in memory which has no name, but contains the value of 13. Figure 13-2 illustrates our current situation. Lines 16 through 18 indicate that it is possible to display the value of this variable using the same method we have used in all earlier lessons of this tutorial. If you remember to add the .all to the access variable, you will be referring to the data stored at the location which it accesses. Line 20 is used to create another variable of type INTEGER somewhere in memory, with Arrow pointing to it, but which contains no value as yet. The next line says to take the value that is stored at the location to which Index points, add 16 to it, and store the result, which should be 29, in the location to which Arrow points. Arrow actually "accesses" the variable, but it is a bit more descriptive to use the word points, especially if you are a Pascal or C programmer. THE THIRD ACCESS VARIABLE _________________________________________________________________ We have not yet used the access variable named There, so we instruct the system, in line 22, to cause it to point to the same piece of data which Arrow is currently accessing. By failing to add the all to the two access variables, we are assigning the access address to There rather than the value which Arrow accesses. If only one of them had the all appended in line 22, there would be a type clash resulting in a compiler error message. All three access variables are accessing some data somewhere, so we can use their .all notation to display all three values. See figure 13-3 for a graphic representation of the current data space. Note that there are actually only two variables, because two of the access variables are pointing at the same piece of data. This is illustrated when one of the variables is changed in line 29, and when the program is executed, two of the values are different. Be sure to compile and run this program. When you think you understand it, see if you can modify it such that all three access variables point to the same piece of data. Page 13-2 Chapter 13 - The Access Type Variable ACCESSING INTEGER AND FLOAT TYPE VARIABLES _________________________________________________________________ Examine the file named ACCESS2.ADA for some =============== additional examples of access type variables. ACCESS2.ADA We begin by declaring two access variables which =============== access INTEGER type variables and three access variables that access FLOAT type variables. It should be pointed out, and it probably comes as no surprise to you, that it is illegal to attempt to access a variable with the wrong type of access variable. Explicit type conversion is possible concerning the data types, but not the access types. Line 19 introduces a new construct, that of initializing a variable when it is created. Using a form similar to qualification, an INTEGER type variable is created somewhere in memory, initialized to 173, and the access variable named Index is assigned its address so that it points to it, or accesses it. After executing line 20, the data space is as shown in figure 13-4. Be sure to note the difference between the expressions in lines 26 and 27. In line 26, the value stored at the place where Index points, is stored at the place where Arrow points. However, in line 27, the access variable Index is caused to point to the same location where the access variable Arrow points. A FLOAT TYPE ACCESS VARIABLE _________________________________________________________________ Line 29 illustrates creation of a FLOAT type variable initialized with the value of Pi. Since the access variable names are used in lines 30 and 31 without the all appended, all three FLOAT type access variables are assigned to access the same variable, and some results are displayed. Figure 13-5 illustrates the condition of the system at this point. The single FLOAT type variable is doubled in line 38, and it is displayed again three different ways. Be sure to compile and execute this program. ACCESSING A RECORD VARIABLE _________________________________________________________________ Examine the example program named ACCESS3.ADA =============== for some additional uses for access variables. ACCESS3.ADA This program begins by defining a record type, =============== then an access type which can be used to access data of this record type. Ignore the procedure Free in line 19 for a short time. In line 22, we declare a variable named Myself which is an access variable that accesses a Page 13-3 Chapter 13 - The Access Type Variable variable of the type MY_RECORD. Since the record does not exist yet, the access variable is actually pointing nowhere. According to the Ada definition, the created access variable will be initialized to the value null, which means it points nowhere. This value can be tested for as we shall see later. All access variables used in an Ada program, regardless of how they are declared, will be initially assigned the value of null. This is true, unless they are specifically initialized to some value as shown in line 23. Line 23 is very interesting because we declare an access variable named Friend, and initialize it by creating a new record somewhere in memory, then initializing the record itself to the values given in the positional aggregate. Finally, the access variable Friend is caused to point to the newly created record. It is permissible to create a new record, but omit the initialization, supplying the initial values in the executable part of the program. We finally declare a BOOLEAN type variable for later use. Figure 13-6 illustrates our current data space. USING THE RECORD ACCESS VARIABLE _________________________________________________________________ In line 29, we create a new variable of type MY_RECORD, which is composed of three separate fields. The three fields are assigned in much the same manner that they were assigned in the chapter where we studied records, so this should pose no problem for you. In line 35, we create another new record somewhere and initialize it to the values given, and cause the variable named Friend to point to it, or access it. See figure 13-7. It should be pointed out that the only data which can be accessed with an access variable are those that are created with the new function. It is not possible to get the address of a statically declared variable and assign that address to an access variable. This is possible in both Pascal and C, but not in Ada. NOW WE HAVE SOME LOST VARIABLES _________________________________________________________________ Consider that the access variable Friend already had some data that it was pointing at, and we told the system to cause it to point at this newly created record. The record it was formerly pointing at is now somewhere in memory, but has nothing pointing at it, so it is in effect lost. We cannot store anything in it, nor can we read out the data that is stored in it. Of even more consequence, we cannot free up those memory locations for further use, so the space is totally lost to our program. Of course, the operating system will take care of cleaning up all of the lost variables when our program terminates, so the data is not lost forever. It is up to Page 13-4 Chapter 13 - The Access Type Variable us to see that we do not lose memory space through clumsy programming because Ada cannot check to see that we have reassigned an access variable. The next interesting thing is illustrated in line 43 where all of the fields of the record which Myself accesses are assigned to all of the fields of the record which Friend accesses. Now it makes sense why the designers of Ada chose to refer to the data which is accessed by the .all notation, it refers to all of the data that the access variable points to. It should be pointed out that as you gain experience with Ada you will find that nearly all access type variables are used to access records, and few, if any, will access scalar variables. BOOLEAN OPERATIONS WITH ACCESS VARIABLES _________________________________________________________________ Records accessed by access variables can be compared for equality or inequality, just like regular records, and they are equal only if all fields in one record are equal to the corresponding fields in the other record. Line 45 will therefore result in TRUE, because the records are identical, due to the assignment in line 43. Access variables can also be compared to each other, and result in TRUE only if they are both pointing to the same object. In line 46, the result is FALSE because they are pointing to different records, even though the records they point to happen to be equal to each other. WHAT IS UNCHECKED DEALLOCATION? _________________________________________________________________ The procedure Unchecked_Deallocation is a required part of Ada so your compiler writer has supplied you with this procedure as a part of the library. Any dynamically allocated data can be freed up for reuse by the system through use of this procedure as illustrated in this program. You must first instantiate a copy of the generic procedure as illustrated in line 19, and name it any available identifier you choose. You must supply two types as parameters, the first being the object type you wish to deallocate, and the second being the access type. The name Free is generally used because that name is used for the equivalent procedure in Pascal and in C. To actually deallocate some storage, you use the name of the access variable which is accessing the storage to be released as the only parameter of the procedure named Free as illustrated in lines 49 and 50. There is a lot more to be said about deallocation of storage and the way it is accomplished, but the details will be left until Page 13-5 Chapter 13 - The Access Type Variable chapter 23, after you gain more experience with Ada. Until then, with your limited knowledge of Ada, you will probably not be writing programs in which you will need this information. Be sure to compile and execute this program. GARBAGE COLLECTION _________________________________________________________________ Another way to deallocate the data accessed by the access variables, is to assign the value of null to the access variables. This will cause the dynamically allocated variables to have no access variables accessing them, and they are then unusable, or garbage. An Ada implementation may implement a garbage collector to search for un-accessed data and reclaim the storage for further use. Implementation of a garbage collector is optional according to the LRM. Much more will be said about deallocation and garbage collection in chapter 23. ACCESSING AN ARRAY OF DATA _________________________________________________________________ The example program named ACCESS4.ADA gives an =============== example of using an access variable to access an ACCESS4.ADA array. The only thing that could be considered =============== new here is the assignment in line 23 where the value of the array List_Of_Stuff, is assigned to the variable which is accessed by the access variable There. Note that 6 INTEGER type values are actually assigned in this one statement. Note that Unchecked_Deallocation is illustrated here also as an example. The program should be simple for you to follow, and after you understand it, compile and execute it. AN ARRAY OF ACCESS VARIABLES _________________________________________________________________ Examine the program ACCESS5.ADA for an example =============== including an array of access variables which is ACCESS5.ADA declared in line 20. The variable named Class =============== is composed of a total of ten access type variables, any of which can be used to point to a variable of type MY_RECORD. The loop in lines 29 through 32 is used to first create a record variable, then assign values to the fields of the created record variable, for each of the ten access variables. Since each record is composed of three subfields, a total of 30 separate variables are created and assigned values in this loop. A few of the variables are reassigned values in lines Page 13-6 Chapter 13 - The Access Type Variable 34 through 40 for illustrative purposes, and the entire array named Class is displayed on the monitor. Compile and run this program, and be sure you understand the resulting printout. The access variable will be very important when we study some of the advanced programming techniques later in this tutorial. PROGRAMMING EXERCISES _________________________________________________________________ 1. Declare a record named BOX_TYPE composed of three FLOAT type elements, Length, Width, and Height. Use the new function to create three boxes named Small, Medium, and Large, and store suitable values in all nine fields. Display the data concerning the three boxes along with the volume of each box. 2. Add the Unchecked_Deallocation procedure to the other three example programs, ACCESS1.ADA, ACCESS2.ADA, and ACCESS5.ADA, and deallocate all allocated variables. Page 13-7